package Testing;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import com.sun.org.apache.xalan.internal.xsltc.util.IntegerArray;

import monsterRun.common.model.Constants;
import monsterRun.common.model.MessageFactory;
import monsterRun.common.model.Position;
import monsterRun.common.model.enums.Direction;
import monsterRun.common.model.enums.GameBoardType;
import monsterRun.common.model.enums.GameMode;
import monsterRun.server.model.Game;
import monsterRun.server.model.MonsterRunServer;
import monsterRun.server.model.entities.Player;
import monsterRun.server.model.entities.PlayerInfo;

public class PlayerMessagesImpl extends UnicastRemoteObject implements
		PlayerMessagesInterface
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static boolean IsGameCreator = true;
	private static Game game;
	private static MonsterRunServer server;
	private int userID;
	private int startPos;
	private HashMap<Integer, PlayerCallBackInterface> pcbiList;

	public PlayerMessagesImpl(MonsterRunServer server) throws RemoteException
	{
		super();
		this.server = server;
		pcbiList = server.getPcbiList();
	}

	@Override
	public int playerMove(int playerId, Position position, int move)
			throws RemoteException
	{
		server.handleMoveRequest(playerId, position, move);
		return 0;
	}

	@Override
	public boolean createGameDetails(int number, GameBoardType board,
			GameMode mode) throws RemoteException
	{
		return createGameBoard(number, board, mode);
	}

	@Override
	public void createDetailsResponse(int userID) throws RemoteException
	{
		this.userID = userID;
	}

	@Override
	public void createJoinGameRequest(int userID, String connectionDetails)
			throws RemoteException
	{
		System.out.println(userID + " ~ WAITING FOR JOIN GAME LOCK ~");
System.out.println("Connection Details are: "+connectionDetails);
		// Synchronize the game joining and creating
		server.acquireMutex();

		System.out.println(userID + " + JOIN GAME LOCK ACQUIRED +");

		// Check if first client for the server
		addPlayerCallBackInterface(userID, connectionDetails);
		server.releaseMutex();
	}

	@Override
	public ArrayList<Integer> createStartPosResponse(int userID, int index)
			throws RemoteException
	{
		// TODO For Ian:For choosing starting position
		System.out.println("StartPosResponse called");
		server.releaseMutex();
		handleStartPositionMessage(userID, index);
		return getAvailablePositions();
	}

	private void handleStartPositionMessage(int userID, int startPos2)
	{

		// Add player to the game if position was valid
		// TODO: For Ian resolve associating user ID's with pcbis
		if (server.addPlayer(pcbiList.get(new Integer(userID)), userID,
				startPos2))
		{
			// Start game if required number of players have joined in
			if (server.isLastPlayer())
			{
				if (Constants.IS_DEBUG)
				{
					System.out.println(server.getPlayers());
				}
				server.startGame();
			}
		}

		System.out.println(userID + " - JOIN GAME LOCK RELEASED-");
		server.releaseMutex();
	}

	@Override
	public boolean isGameCreator()
	{
		if (IsGameCreator == true)
		{
			IsGameCreator = false;
			return true;
		}
		else
		{
			return false;
		}
	}

	@Override
	public ArrayList<Integer> getAvailablePositions() throws RemoteException
	{

		return server.getGame().getAvailablePositions();

	}

	private boolean createGameBoard(int numPlayers, GameBoardType board,
			GameMode mode)
	{

		// Validate input
		if ((numPlayers < Constants.MIN_PLAYERS || numPlayers > Constants.MAX_PLAYERS))
		{
			String error = "Please select a number between 2 and 4";
			// comm.sendMessage(MessageFactory.createInvalidInput(error));
			return false;
		}
		// Send message confirming successful game creation
		else
		{

			System.out.println("Board is: " + board);
			System.out.println("Game mode is: " + mode);
			System.out.println("Number of players is: " + numPlayers);

			server.getGame().setGameMode(mode);
			server.getGame().setBoardStyle(board);
			server.getGame().setNumberOfPlayers(numPlayers);
			// comm.sendMessage(MessageFactory.createNumPlayerSuccess());
			// comm.sendMessage(MessageFactory.createStartPosRequest(server
			// .getGame().getAvailablePositions()));

			System.out.println(userID + "- GAME CREATED LOCK RELEASED -");
			return true;
		}
	}

	@Override
	public void setCreatorStatus(boolean status) throws RemoteException
	{
		IsGameCreator = status;
	}

	public void addPlayerCallBackInterface(int userID, String connectionDetails)
			throws RemoteException
	{
		PlayerCallBackInterface pcbi = null;

		try
		{
			pcbi = (PlayerCallBackInterface) Naming.lookup(connectionDetails);
			if (pcbiList.size() < Constants.MAX_PLAYERS)
			{
				pcbiList.put(userID, pcbi);
			}
		}
		catch (MalformedURLException e)
		{
			e.printStackTrace();
		}
		catch (NotBoundException e)
		{
			e.printStackTrace();
		}

	}

	public PlayerCallBackInterface getPlayerCallBackInterface()
			throws RemoteException
	{
		// TODO for Ian: Need to resolve this
		return null;
	}

	@Override
	public boolean sendLoginDetails(String[] details) throws RemoteException
	{
		try
		{
			// PlayerInfo pi = new PlayerInfo(details[0], details[1]);
			// this.userID = details[0];
			PlayerInfo pi = new PlayerInfo();
			if (!pi.login(details[0], details[1]))
			{
				return false;
			}
			return true;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public boolean createRegistrationRequest(String[] details)
			throws RemoteException
	{
		try
		{
			PlayerInfo pi = new PlayerInfo();
			if (!pi.addPlayerInfo(details[0], details[1], details[2],
					Integer.parseInt(details[3]), details[4], details[5]))
			{
				return false;
			}
			else
			{
				return true;
			}
		}
		catch (Exception e)
		{
			System.out.println("Problem with registration");
			e.printStackTrace();
			return false;
		}

	}

}
